uniform float pointRadius;
uniform float noiseFreq = 10.0;
uniform float noiseAmp = 0.5;
uniform vec3 halfVectorEye;
uniform vec2 invViewport;
uniform sampler2D shadowTex;
//uniform sampler3D noiseTex;
uniform sampler2D depthTex;
uniform float depthFade = 0.2;

void main()
{
    // calculate eye-space sphere normal from texture coordinates
    vec3 N;
    N.xy = gl_TexCoord[0].xy*vec2(2.0, -2.0) + vec2(-1.0, 1.0);
    float r2 = dot(N.xy, N.xy);
    if (r2 > 1.0) discard;   // kill pixels outside circle
    N.z = sqrt(1.0-r2);

    vec4 eyeSpacePos = gl_TexCoord[1];
    vec4 eyeSpaceSpherePos = vec4(eyeSpacePos.xyz + N*pointRadius, 1.0); // point on sphere

    vec4 shadowPos = gl_TextureMatrix[0] * eyeSpaceSpherePos;
    float shadow = 1.0 - texture2DProj(shadowTex, shadowPos.xyw).x;
//    vec3 shadow = 1.0 - texture2DProj(shadowTex, shadowPos.xyw).xyz;

    vec4 worldSpacePos = gl_ModelViewMatrixInverse * eyeSpacePos;
    //float4 noise = texture3D(noiseTex, worldSpacePos.xyz*noiseFreq);
    //r2 += noise.x * noiseAmp;

//    float alpha = exp(-r2*4.0);
    float alpha = 1.0 - r2;
    alpha *= gl_Color.w;

    // opacity correction
    vec3 v = normalize(eyeSpacePos); // local view vector
    float opacityCorrect = abs(dot(v, halfVectorEye));
//    alpha /= opacityCorrect;

    // "soft" particles

    // get scene depth
    vec2 uv = gl_FragCoord.xy * invViewport;
    float sceneDepth = texture2D(depthTex, uv).x;
    // transform to eye space
    vec4 scenePos = vec4(uv, sceneDepth, 1.0)*2.0-1.0;          // ndc
    vec4 scenePosEye = gl_ProjectionMatrixInverse * scenePos;   // hopefully this will get optimized by compiler
    scenePosEye.z /= scenePosEye.w;

    // calc difference between scene depth and particle depth
//    float depthDiff = sceneDepth - gl_FragCoord.z;    // not really correct
    float depthDiff = eyeSpacePos.z - scenePosEye.z;
    float soften = saturate(depthDiff / depthFade);

    alpha *= soften;

//    gl_FragColor = vec4(gl_Color.xyz * alpha, alpha);
//    gl_FragColor = vec4(gl_Color.xyz * shadow, alpha);
    gl_FragColor = vec4(gl_Color.xyz * shadow * alpha, alpha);  // premul alpha
//    gl_FragColor = vec4(sceneDepth.xxx, 1.0);
//    gl_FragColor = vec4(depthDiff.xxx * 10.0, 1.0);
//    gl_FragColor = vec4(soften.xxx, 1.0);
//    gl_FragColor = vec4(opacityCorrect.xxx, 1.0);
//    gl_FragColor = vec4(shadow.xxx * alpha, alpha);
//    gl_FragColor = vec4(shadow.xxx, 1.0);
}